<?php
namespace Admin\Controller;
use Lib\Controller\AdminBaseController;

class RoleController extends AdminBaseController{
    private $Admin;
    private $Role;
    private $Access;
    private $bbsAdmin;
    private $businessUser;
    private $bbsShopAreas;
    private $shopUser;
    private $fileLogic;
    private $su;
    private $shopUserInfo;
    private $Menu;
    private $shopDesc;
 
    public function __construct(){
        $this->Admin = D("Admin");
        $this->Role = D("Role");
        $this->Access = D("Access");
        $this->Menu = D("Menu");
        $this->bbsAdmin = D("BbsAdmin");
        $this->businessUser = D("BusinessUser");
        $this->bbsShopAreas = D("ShopAreas");
        $this->shopUser = M('User','shop_','DB_CONFIG2');
        $this->shopUserInfo = M('UserInfo','shop_','DB_CONFIG2');
        $this->su = D('User');
        $this->fileLogic = new \Lib\ORG\FileLogic();
        $this->shopDesc = D('ShopDesc');
        parent::__construct();
    }
    /**
     * 后台管理员列表
     */
    public function admin_list(){
        
        $where['id'] = session('adminId');
        $adminInfo = $this->Admin->find_admin($where); 
        if($adminInfo['role_id']==1){
            $allAdmin = $this->Admin->find_admin();
            $accessList = $this->Role->getAccess($allAdmin);
        }else{
            unset($where);
            $where['store_id'] = $adminInfo['store_id'];
            $allAdmin = $this->Admin->select_admin($where);
            $accessList = $this->Role->getAccess($allAdmin);
        }
        foreach ($accessList as $key => $value){
            $accessList[$key]['create_time'] = date("Y-m-d H:i:s", $value['create_time']);
            $accessList[$key]['update_time'] = date("Y-m-d H:i:s", $value['update_time']);
        }
        $this->assign('accessList',$accessList);
        $this->display();
    }
    
    
    /**
     * 前台管理员列表
     */
    public function B2C_admin_list(){
        $where['id'] = session('adminId');
        //$adminInfo = $this->shopUser->where($where)->find();
        $adminInfo = $this->Admin->find_admin($where);
        if($adminInfo['role_id']==1){
            //$allAdmin = $this->shopUser->where('role_id!=0')->select();
            $allAdmin = $this->shopUser->alias('as u')->field('u.*,ui.avatar_img,ui.nick_name')->join(C('DB_PREFIX_B2C').'user_info as ui ON u.id = ui.user_id')->where('role_id!=0')->select();
            $accessList = $this->Role->b2cGetAccess($allAdmin);
        }else{
            //$allAdmin = $this->shopUser->where('role_id!=0 and store_id = '.session('shop_id'))->select();
            $allAdmin = $this->shopUser->alias('as u')->field('u.*,ui.avatar_img,ui.nick_name')->join(C('DB_PREFIX_B2C').'user_info as ui ON u.id = ui.user_id')->where('role_id!=0 and store_id = '.session('shop_id'))->select();
            $accessList = $this->Role->b2cGetAccess($allAdmin);
        }
        foreach ($accessList as $key => $value){
            $accessList[$key]['create_time'] = date("Y-m-d H:i:s", $value['create_time']);
            $accessList[$key]['update_time'] = date("Y-m-d H:i:s", $value['update_time']);
        }
        //p($accessList);
        $this->assign('accessList',$accessList);
        $this->display();
    } 
    
    /**
     * 编辑管理员
     */
    public function edit_admin(){
        if(IS_GET){
            $where['id'] = I('get.id');
            $adminInfo = $this->Admin->find_admin($where);
//             p($adminInfo);
            $this->assign('adminInfo',$adminInfo);
            $this->assign('type',I('get.type'));
            $this->display();
        }
        if(IS_POST){
            $where['id'] = I('post.adminInfoId');
            $adminInfo = $this->Admin->find_admin($where);
            $data['user_name'] = I('post.user_name');
            if(I('post.password')==''){
                $data['user_password'] = $adminInfo['user_password'];
            }else{
                $data['user_password'] = md5(I('post.password').$adminInfo['user_salt']);
            }
            $data['avatar_img'] = I('post.avatar_img', '');
            $data['nick_name'] = I('post.nick_name');
            $data['about'] = I('post.about');
            $update = $this->Admin->update_admin($where,$data);
            
            if($update !==false){
                $this->tyAjaxReturn(1, L('保存成功'), U(MODULE_NAME.'/Role/admin_list'));
            }else{
                $this->tyAjaxReturn(0, L('保存失败'));
            }
        }
    }
    
    /**
     * 添加管理员
     */
    public function add_admin() {
        if (IS_POST) {
            //验证密码
            $data['type'] = I('post.type', '');
            
            
            $data['password'] = i('post.password', '');
            $data['repassword'] = I('post.repassword', '');
            $data['avatar_img'] = I('post.avatar_img', '');
            $data['nick_name'] = I('post.nick_name');
            $data['about'] = I('post.about');
            //$data['user_name'] = I('post.email', '');
            //$this->ajaxReturn(p(session('adminId')));
            
        
            //密码格式
            if (!preg_match('/^[A-Za-z0-9\@\!\#\$\%\^\&\*\.\~]{9,16}$/', $data['password'])) {
                $this->tyAjaxReturn(0, '密码格式不正确！9~16个字符');
            } elseif ($data['password'] != $data['repassword']) {//判断密码一致   
                $this->tyAjaxReturn(0, '两次输入的密码不一致');
            }
            
            
            
            if($data['type'] == 1) {
                if ($this->bbsAdmin->create()) {
                    //添加用户数据
                    if ($this->bbsAdmin->add() > 0) {
                        $this->tyAjaxReturn(1, L('添加成功'), U(MODULE_NAME.'/Role/admin_list'));
                    } else {
                        $this->tyAjaxReturn(0, $this->bbsAdmin->getError());
                    }
                } else {
                    $this->tyAjaxReturn(0, $this->bbsAdmin->getError());
                }
            }else{
                $avatar_img = I('post.avatar_img', '');
                $admin_status = I('post.status',0);
                //$this->tyAjaxReturn($data);
                //$this->ajaxReturn($data['avatar_img']);
                if ( empty($avatar_img) ){
                    $this->tyAjaxReturn(0, '没有图片');
                }
                if ($this->su->create()) {
                    //添加用户数据
                    $id = $this->su->add();
                    //$this->ajaxReturn($id);
                    if ($id > 0) {
                        
                        $this->shopUser->id = $id;
                        $this->shopUser->admin_status = $admin_status;
                        if ($this->shopUser->save()) {
                            if($this->shopUserInfo->add(array('avatar_img' => $avatar_img , 'user_id' => $id))>0){
                                $this->tyAjaxReturn(1, L('添加成功'), U(MODULE_NAME.'/Role/B2C_admin_list'));
                            } else {
                                $this->tyAjaxReturn(0,$this->shopUserInfo->getError());
                            }
                        } else {
                            $this->tyAjaxReturn(0, $this->shopUser->getError());
                        }
                    } else {
                        $this->tyAjaxReturn(0, $this->su->getError());
                    }
                } else {
                    $this->tyAjaxReturn(0, $this->su->getError());
                }
                
                
                
            }
            
            
            
            
            
        } else {
            //获取角色列表
            //p(session('roleId'));
            $roleList = $this->_getRoleList();
            //p($roleList);
            $storeList = $this->_getStoreList();
            //p($storeList);
            //p($storeList);
            $res = $this->businessUser->field('id')->where(array('audit_status' => array('eq', 1), 'store_status' => array('gt', 0)))->find();
            $id = $res['id'];
            $areasList = $this->_getAreasList($id);
            //p($id);
            //p($areasList);
            $descList = $this->_getDescList($id, $areasList[0]['id']);
            //p($descList);
            //p($areasList[0]['id']);
            
            //p($storeList);
            //p($areasList);
            //session('shop_id',1);
            //p(session('shop_id'));
            $this->assign('descList',$descList);
            $this->assign('areasList', $areasList);
            $this->assign('roleList', $roleList);
            $this->assign('storeList', $storeList);
            $this->assign('userInfo', null);
            $this->display('edit_admin');
        }
    }
    
    
    
    
    
    
    
    
    
    private function _getDescList($sid, $aid) {
       $descList = $this->shopDesc->where(array('shop_id' => $sid,'areas_id' =>$aid))->select();
       //p($this->shopDesc->getLastSql());
       return $descList;
    }
    
    
    
    
    /**
     * 获取角色列表
     * @return type
     */
    private function _getRoleList() {
        $roleList = $this->Role->where(array('id' => array('gt', session('roleId')), 'status' => array('gt', 0), 'type' => array('eq',2) ))->select();
        if (!$roleList) {
            //重定向到添加角色操作
            redirect(U(MODULE_NAME.'/Rbac/add_role'), 3, '没有管理员角色，请先添加角色');
        }
        return $roleList;
    }
    
    
    /**
     * 获取商店列表
     * @return type
     */
    private function _getStoreList() {
        if(!session('shop_id')) {
            $storeList = $this->businessUser->where(array('audit_status' => array('eq', 1), 'store_status' => array('gt', 0)))->select();
        } else{
            $storeList = $this->businessUser->where(array('id' => session('shop_id')))->select();
        }
        if (!$storeList) {
            //重定向到添加角色操作
            redirect(U(MODULE_NAME.'/Role/admin_list'), 3, '没有商店，请先添加商店');
        }
        return $storeList;
    }
    
    private function _getAreasList($id) {
        $areasList = $this->bbsShopAreas->where(array('shop_id' => $id))->select();        
        if (!$areasList) {
            //重定向到添加角色操作
            redirect(U(MODULE_NAME.'/Role/admin_list'), 3, '没有地区，请先添加地区');
        }
        return $areasList;
    }
    
    
    
    public function changeStoreList() {
        if(IS_AJAX){
            if(!session('shop_id')) {
                $storeList = $this->businessUser->where(array('audit_status' => array('eq', 1), 'store_status' => array('gt', 0)))->select();
            } else{
                $storeList = $this->businessUser->where(array('id' => session('shop_id')))->select();
            }
            $this->tyAjaxReturn(1,'',null,$storeList,null);
        }
    }
    
    
    
    public function changeFrontRoleList() {
        if(IS_AJAX){
            $roleList = $this->Role->where(array('id' => array('gt', 1), 'status' => array('gt', 0), 'type' => array('eq',1) ))->select();
            $this->tyAjaxReturn(1,'',null,$roleList,null);
        }
    }
    
    
    public function changeBehindRoleList() {
        if(IS_AJAX){
            $roleList = $this->Role->where(array('id' => array('gt', session('roleId')), 'status' => array('gt', 0), 'type' => array('eq',2) ))->select();
            $this->tyAjaxReturn(1,'',null,$roleList,null);
        }
    }
    
    
    
    public function changeAreasList() {
        if(IS_AJAX){
            $id = I('get.id',0);
            $areasList = $this->bbsShopAreas->where(array('shop_id' => $id))->select();
            if (!$areasList) {
                //重定向到添加角色操作
                //redirect(U(GROUP_NAME.'/Rbac/add_role'), 3, '没有地区，请先添加地区');
                $this->tyAjaxReturn(0,'没有地区，请先添加地区',U(MODULE_NAME.'/Area/add_area'),null);
            }
            $this->tyAjaxReturn(1,'',null,$areasList,null);
        
        }
    }
    
    
    public function changeDescList() {
        if(IS_AJAX){
            $sid = I('get.sid',0);
            $aid = I('get.aid',0);
            $descList = $this->_getDescList($sid,$aid);
            if (!$descList) {
                //重定向到添加角色操作
                //redirect(U(GROUP_NAME.'/Rbac/add_role'), 3, '没有地区，请先添加地区');
                $this->tyAjaxReturn(0,'没有社区，请先添加社区',U(MODULE_NAME.'/community/add_community'),null);
            }
            $this->tyAjaxReturn(1,'',null,$descList,null);
    
        }
    }

    
    /**
     * 删除管理员
     */
    public function delete_admin(){
        $where['id'] = I('get.id');
        $result = $this->Admin-> deleteAdmin($where);
        if($result){
            $this->tyAjaxReturn(1,'删除成功',U(MODULE_NAME . '/Role/admin_list'));
        }else{
            $this->tyAjaxReturn(0,'删除失败');
        }
    }
    
    
    /**
     * 删除前台管理员
     * */
    public function B2C_delete_admin(){
         $where1['id'] = I('get.id');
         $where2['user_id'] = I('get.id');
         $result1 = $this->shopUser->where($where1)->delete();
         $result2 = $this->shopUserInfo->where($where2)->delete();
         if($result1){
             $this->tyAjaxReturn(1,'删除成功',U(MODULE_NAME . '/Role/admin_list'));
         }else{
             $this->tyAjaxReturn(0,'删除失败');
         }
    }
    
    
    
    
    /**
     * 角色列表
     */
    public function role_list(){
        $roleList = $this->Role->select();
//         p($roleList);
        $this->assign('roleList',$roleList);
        $this->display();
    }
    
    /**
     * 编辑角色
     */
    public function edit_role(){
        if(IS_GET){
            $where['id'] = I("get.id",'');
            $result = $this->Role->findRole($where);
            $this->assign('roleInfo',$result);
            $this->display();
        }
        if(IS_POST){
            $where['id'] = I('post.id','');
            $where['name'] = I('post.name','');
            $where['remark'] = I('post.remark','');
            $where['status'] = I('post.status',1);
//             p($where);
            $result = $this->Role->updateRole($where);
            if($result){
                $this->tyAjaxReturn(1,'修改成功',U(MODULE_NAME . '/Role/role_list'));
            }else{
                $this->tyAjaxReturn(0,'修改失败');
            }
        }
    }
    
    /**
     * 修改角色状态
     */
    public function change_role_status(){
        $id = I('get.id', '', 'int');
        if ($id == '' || $id == C('SUPER_ADMIN_ROLE_ID')) {
            $this->tyAjaxReturn(0, '超级管理员不可修改');
        }
        $where['id'] = $id;
        $data = $this->Admin->find_admin($where);
        //查询之前状态
        //$data = $this->Role->field('status')->find($id);
    
        $status = $data['status'] > 0 ? 0 : 1;
    
        $result = $this->Admin->where(array('id' => $id))->save(array('status' => $status,'update_time' => time()));
    
        if ($result > 0) {
            $this->tyAjaxReturn(1, '修改成功！');
        } else {
            $this->tyAjaxReturn(0, '修改失败！');
        }
    }
    
    
    public function B2C_change_role_status(){
        $id = I('get.id', '', 'int');
        $where['id'] = $id;
        $data = $this->shopUser->where($where)->find();
        
        //$this->ajaxReturn($data);
        
        $status = $data['admin_status'] > 0 ? 0: 1;
        $result = $this->shopUser->where($where)->save(array('admin_status' => $status,'update_time' => time()));
        
        if ($result > 0) {
            $this->tyAjaxReturn(1, '修改成功！');
        } else {
            $this->tyAjaxReturn(0, '修改失败！');
        }
    }
    
    /**
     * 设置权限
     */
    public function edit_access(){
        if(IS_GET){
            $roleId['id'] = I('get.id', '', 'int');
            if ($roleId == C('SUPER_ADMIN_ROLE_ID') || empty($roleId)) {
                $this->error('超级管理员不能设置');
            }
            //获取角色信息
            $roleInfo = $this->Role->findRole($roleId);
            //菜单列表
            $menuList = M('Menu')->select();
            //原有权限
            $originalAccess = $this->Access->where(array('role_id' => $roleId['id'],'access_type' => '2'))->select();
            $originalMenuList = array();
            //提取菜单id
                foreach ($originalAccess as$w=> $val) {
                    $originalMenuList [$w] = $val['access_type_id'];
                }
            $accessInfo = arrayMerge($menuList, $originalMenuList);
            $this->assign('originalMenuList',$originalMenuList);
            $this->assign('originalAccess',$originalAccess);
            $this->assign('roleInfo', $roleInfo);
            $this->assign('access', $accessInfo);
            $this->display();
        }
        if(IS_POST){
            $roleId = I('post.role_id', '', 'int');
            if (empty($roleId) || $roleId == C('SUPER_ADMIN_ROLE_ID')) {
                $this->tyAjaxReturn(0, '超级管理员不能设置');
            }
            $accessList = I('post.access');
            foreach($accessList as$w=> $access){
                $aa = $this->Menu->field('p_id')->where(array('id'=>$access))->find();
                foreach($aa as$q=> $bb){
                    $pId[$w] = $bb;
                }
            }
            $pId = array_unique($pId);//array_unique函数去除数组内重复的元素
            foreach($pId as$x=>$p_id){
                $cc = $this->Menu->field('p_id')->where(array('id'=>$p_id))->find();
                foreach($cc as$e=> $dd){
                    $cp_Id[$x] = $dd;
                }
            }
            $cp_Id = array_unique($cp_Id);
            $array = array_merge($pId,$cp_Id);
            $accessList = array_merge($accessList,$array);
            //删除原有权限
            $this->Access->where(array('role_id' => $roleId,'access_type' => '2'))->delete();
            
            //添加新权限
            foreach ($accessList as $val) {
                $data['role_id'] = $roleId;
                $data['access_type'] = 2;
                $data['access_type_id'] = $val;
                $data['access_status'] = 1;
                $this->Access->add($data);
            }
            $this->tyAjaxReturn(1, '权限设置成功！', U(MODULE_NAME.'/Role/role_list'));
        }
        
    }
    
    
    /**
     * 此方法仅用JS表单验证测试
     * 测试邮箱是否存在
     */
    public function check_email() {
        $email = I('email', '');
        $count = $this->bbsAdmin->where(array('user_name' => $email))->count();
        if ($count > 0) {
            $this->tyAjaxReturn(0, "邮箱已存在");
        } else {
            $this->tyAjaxReturn(1, "");
        }
    }
    

    /**
     * 设置页面元素权限
     */
    public function edit_power(){
        if(IS_GET){
            $roleId['id'] = I('get.id', '', 'int');
            if ($roleId == C('SUPER_ADMIN_ROLE_ID') || empty($roleId)) {
                $this->error('超级管理员不能设置');
            }
            //获取角色信息
            $roleInfo = $this->Role->findRole($roleId);
            //页面元素列表
            $pageList = M('Page')->select();
            //原有权限
            $originalAccess = $this->Access->where(array('role_id' => $roleId['id'],'access_type' => '1'))->select();
            foreach($originalAccess as$x=>$val){
                $originalMenuList [$x] = $val['access_type_id'];
            }
            foreach($pageList as$y=> $page){
                if($page['id']==$originalMenuList[$y]){
                    $pageList[$y]['is_checked'] = 1;
                }else{
                    $pageList[$y]['is_checked'] = 0;
                }
            }
            $this->assign('roleInfo',$roleInfo);
            $this->assign('pageList',$pageList);
            $this->assign('originalAccess',$originalAccess);
            $this->display();
        }
        if(IS_POST){
            $roleId = I('post.role_id', '', 'int');
            if (empty($roleId) || $roleId == C('SUPER_ADMIN_ROLE_ID')) {
                $this->tyAjaxReturn(0, '超级管理员不能设置');
            }
            $accessList = I('post.access');
            //删除原有权限
            $this->Access->where(array('role_id' => $roleId,'access_type' => '1'))->delete();
            //添加新权限
            foreach ($accessList as $val) {
                $data['role_id'] = $roleId;
                $data['access_type'] = 1;
                $data['access_type_id'] = $val;
                $data['access_status'] = 1;
                $this->Access->add($data);
            }
            $this->tyAjaxReturn(1, '权限设置成功！', U(MODULE_NAME.'/Role/role_list'));
        }
    }
    
    
    public function upload_logo_pc_crop(){
        $this->upload_crop(User, avatar_img, 150, 150);
    }
    
    /**
     * 裁剪图片方法
     * @access private
     * @param string $folderPname  创建父文件夹名
     * @param string $foldername  创建子文件夹名
     * @param int $saveWidth  保存图片宽度,不填时默认200
     * @param int $saveHeight 保存图片高度,不填时默认200
     * @return void
     */
    private function upload_crop($folderPname,$foldername,$saveWidth,$saveHeight){
        $userID = session('shop_id');
        //$userID = 1;
        $this->fileLogic->createFolder($userID,$folderPname,$foldername); //创建文件夹的逻辑
        $savePath  = C('UPLOAD_ALLSHOP_PATH') . 'userID_'.$userID.DS.$folderPname.DS.$foldername.DS; // 上传文件保存路径
        //create file
        //传入文件夹参数给上传类
        //import('crop');
                    
        $crop = new CropAvatar(
            isset($_POST['avatar_src']) ? $_POST['avatar_src'] : null,
            isset($_POST['avatar_data']) ? $_POST['avatar_data'] : null,
            isset($_FILES['avatar_file']) ? $_FILES['avatar_file'] : null,
            isset($savePath) ? $savePath : null , //保存路径
            isset($saveWidth) ? $saveWidth : 200 , //保存图片宽度,不填时默认200
            isset($saveHeight) ? $saveHeight : 200  //保存图片高度,不填时默认200
        );
        $response = array(
            'state'  => 200,
            'message' => $crop -> getMsg(),
            'result' => $crop -> getResult()
        );
    
        if(!empty($response['result'])){
            $dirname = strstr($response['result'],"userID");
            $dirname = str_replace('\\', '/', $dirname);
            $this->tyajaxReturn(1,'裁剪成功','',$dirname);
        }else{
            echo json_encode($response);
        }
    }
    
    
}















































class CropAvatar {
    private $src;
    private $data;
    private $dst;
    private $type;
    private $extension;
    private $msg;
    private $saveSrc;
    function __construct($src, $data, $file, $saveSrc, $save_width = 200 , $save_height = 200) {
        $this -> setSaveSrc($saveSrc);
        $this -> setSrc($src);
        $this -> setData($data);
        $this -> setFile($file);
        $this -> crop($this -> src, $this -> dst, $this -> data, $save_width, $save_height);
    }

    private function setSrc($src) {
        if (!empty($src)) {
            $type = exif_imagetype($src);

            if ($type) {
                $this -> src = $src;
                $this -> type = $type;
                $this -> extension = image_type_to_extension($type);
                $this -> setDst();
            }
        }
    }

    private function setData($data) {
        if (!empty($data)) {
            $this -> data = json_decode(stripslashes($data));
        }
    }

    private function setFile($file) {
        $errorCode = $file['error'];
        $filename = explode('.',$file['name']);
        $filename[0] = md5($filename[0].date('YmdHis'));
        if ($errorCode === UPLOAD_ERR_OK) {
            $type = exif_imagetype($file['tmp_name']);

            if ($type) {
                $extension = image_type_to_extension($type);

                $original_dir = dirname($this->saveSrc).DS.'original';//源文件路径
                mkdirm($original_dir.DS.date('Ym')); //创建以时间分类的文件夹

                $src = $original_dir . DS . date('Ym') . DS . $filename[0] . '.original' . $extension;
                 
                if ($type == IMAGETYPE_GIF || $type == IMAGETYPE_JPEG || $type == IMAGETYPE_PNG) {

                    if (file_exists($src)) {
                        unlink($src);
                    }
                    $result = move_uploaded_file($file['tmp_name'], $src);
                    if ($result) {
                        $this -> src = $src;
                        $this -> type = $type;
                        $this -> extension = $extension;
                        $this -> setDst();
                    } else {
                        $this -> msg = 'Failed to save file';
                    }
                } else {
                    $this -> msg = 'Please upload image with the following types: JPG, PNG, GIF';
                }
            } else {
                $this -> msg = 'Please upload image file';
            }
        } else {
            $this -> msg = $this -> codeToMessage($errorCode);
        }
    }

    private function setDst($file) {
        $filename = explode('.',$file['name']);
        $filename[0] = md5($filename[0].date('YmdHis'));
        mkdirm($this->saveSrc.DS.date('Ym'));
        $this -> dst = $this->saveSrc  . date('Ym') . DS . $filename[0] . '.png';
    }

    private function setSaveSrc($saveSrc) {
        if (!empty($saveSrc)) {
            $this -> saveSrc = $saveSrc;
        }
    }

    private function crop($src, $dst, $data,$save_width,$save_height) {
        if (!empty($src) && !empty($dst) && !empty($data)) {
            switch ($this -> type) {
                case IMAGETYPE_GIF:
                    $src_img = imagecreatefromgif($src);
                    break;

                case IMAGETYPE_JPEG:
                    $src_img = imagecreatefromjpeg($src);
                    break;

                case IMAGETYPE_PNG:
                    $src_img = imagecreatefrompng($src);
                    break;
            }

            if (!$src_img) {
                $this -> msg = "Failed to read the image file";
                return;
            }

            $size = getimagesize($src);
            $size_w = $size[0]; // natural width
            $size_h = $size[1]; // natural height

            $src_img_w = $size_w;
            $src_img_h = $size_h;

            $degrees = $data -> rotate;

            // Rotate the source image
            if (is_numeric($degrees) && $degrees != 0) {
                // PHP's degrees is opposite to CSS's degrees
                $new_img = imagerotate( $src_img, -$degrees, imagecolorallocatealpha($src_img, 0, 0, 0, 127) );

                imagedestroy($src_img);
                $src_img = $new_img;

                $deg = abs($degrees) % 180;
                $arc = ($deg > 90 ? (180 - $deg) : $deg) * M_PI / 180;

                $src_img_w = $size_w * cos($arc) + $size_h * sin($arc);
                $src_img_h = $size_w * sin($arc) + $size_h * cos($arc);

                // Fix rotated image miss 1px issue when degrees < 0
                $src_img_w -= 1;
                $src_img_h -= 1;
            }

            $tmp_img_w = $data -> width;
            $tmp_img_h = $data -> height;
            $dst_img_w = $save_width;
            $dst_img_h = $save_height;

            $src_x = $data -> x;
            $src_y = $data -> y;

            if ($src_x <= -$tmp_img_w || $src_x > $src_img_w) {
                $src_x = $src_w = $dst_x = $dst_w = 0;
            } else if ($src_x <= 0) {
                $dst_x = -$src_x;
                $src_x = 0;
                $src_w = $dst_w = min($src_img_w, $tmp_img_w + $src_x);
            } else if ($src_x <= $src_img_w) {
                $dst_x = 0;
                $src_w = $dst_w = min($tmp_img_w, $src_img_w - $src_x);
            }

            if ($src_w <= 0 || $src_y <= -$tmp_img_h || $src_y > $src_img_h) {
                $src_y = $src_h = $dst_y = $dst_h = 0;
            } else if ($src_y <= 0) {
                $dst_y = -$src_y;
                $src_y = 0;
                $src_h = $dst_h = min($src_img_h, $tmp_img_h + $src_y);
            } else if ($src_y <= $src_img_h) {
                $dst_y = 0;
                $src_h = $dst_h = min($tmp_img_h, $src_img_h - $src_y);
            }

            // Scale to destination position and size
            $ratio = $tmp_img_w / $dst_img_w;
            $dst_x /= $ratio;
            $dst_y /= $ratio;
            $dst_w /= $ratio;
            $dst_h /= $ratio;

            $dst_img = imagecreatetruecolor($dst_img_w, $dst_img_h);

            // Add transparent background to destination image
            imagefill($dst_img, 0, 0, imagecolorallocatealpha($dst_img, 0, 0, 0, 127));
            imagesavealpha($dst_img, true);

            $result = imagecopyresampled($dst_img, $src_img, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);

            if ($result) {
                if (!imagepng($dst_img, $dst)) {
                    $this -> msg = "Failed to save the cropped image file";
                }
            } else {
                $this -> msg = "Failed to crop the image file";
            }

            imagedestroy($src_img);
            imagedestroy($dst_img);
        }
    }

    private function codeToMessage($code) {
        $errors = array(
            UPLOAD_ERR_INI_SIZE =>'The uploaded file exceeds the upload_max_filesize directive in php.ini',
            UPLOAD_ERR_FORM_SIZE =>'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form',
            UPLOAD_ERR_PARTIAL =>'The uploaded file was only partially uploaded',
            UPLOAD_ERR_NO_FILE =>'No file was uploaded',
            UPLOAD_ERR_NO_TMP_DIR =>'Missing a temporary folder',
            UPLOAD_ERR_CANT_WRITE =>'Failed to write file to disk',
            UPLOAD_ERR_EXTENSION =>'File upload stopped by extension',
        );

        if (array_key_exists($code, $errors)) {
            return $errors[$code];
        }

        return 'Unknown upload error';
    }

    public function getResult() {
        return !empty($this -> data) ? $this -> dst : $this -> src;
    }

    public function getMsg() {
        return $this -> msg;
    }
}

function mkdirm($path) {
    if (!file_exists($path)) {
        mkdirm(dirname($path));
        mkdir($path, 0777);
    }
}

?>